home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / nethack.lha / nethack-3.1 / src / dbridge.c < prev    next >
C/C++ Source or Header  |  1992-12-22  |  22KB  |  938 lines

  1. /*    SCCS Id: @(#)dbridge.c    3.1    92/10/24    */
  2. /*    Copyright (c) 1989 by Jean-Christophe Collet */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. /*
  6.  * This file contains the drawbridge manipulation (create, open, close,
  7.  * destroy).
  8.  *
  9.  * Added comprehensive monster-handling, and the "entity" structure to 
  10.  * deal with players as well. - 11/89
  11.  */
  12.  
  13. #include "hack.h"
  14.  
  15. #ifdef OVLB
  16. static void FDECL(get_wall_for_db, (int *, int *));
  17. static struct entity *FDECL(e_at, (int, int));
  18. static void FDECL(m_to_e, (struct monst *, XCHAR_P, XCHAR_P, struct entity *));
  19. static void FDECL(u_to_e, (struct entity *));
  20. static void FDECL(set_entity, (int, int, struct entity *));
  21. static char *FDECL(e_nam, (struct entity *));
  22. #ifdef D_DEBUG
  23. static char *FDECL(Enam, (struct entity *)); /* unused */
  24. #endif
  25. static char *FDECL(E_phrase, (struct entity *, const char *));
  26. static boolean FDECL(e_survives_at, (struct entity *, int, int));
  27. static void FDECL(e_died, (struct entity *, int, int));
  28. static boolean FDECL(automiss, (struct entity *));
  29. static boolean FDECL(e_missed, (struct entity *, BOOLEAN_P));
  30. static boolean FDECL(e_jumps, (struct entity *));
  31. static void FDECL(do_entity, (struct entity *));
  32. #endif /* OVLB */
  33.  
  34. #ifdef OVL0
  35.  
  36. boolean
  37. is_pool(x,y)
  38. int x,y;
  39. {
  40.        register schar ltyp = levl[x][y].typ;
  41.        if(ltyp == POOL || ltyp == MOAT || ltyp == WATER) return TRUE;
  42.        if(ltyp == DRAWBRIDGE_UP &&
  43.                (levl[x][y].drawbridgemask & DB_UNDER) == DB_MOAT) return TRUE;
  44.        return FALSE;
  45. }
  46.  
  47. boolean
  48. is_lava(x,y)
  49. int x,y;
  50. {
  51.        register schar ltyp = levl[x][y].typ;
  52.        if(ltyp == LAVAPOOL ||
  53.       (ltyp == DRAWBRIDGE_UP &&
  54.        (levl[x][y].drawbridgemask & DB_UNDER) == DB_LAVA)) return TRUE;
  55.        return FALSE;
  56. }
  57.  
  58. boolean
  59. is_ice(x,y)
  60. int x,y;
  61. {
  62.     register schar ltyp = levl[x][y].typ;
  63.     if (ltyp == ICE ||
  64.         (ltyp == DRAWBRIDGE_UP &&
  65.         (levl[x][y].drawbridgemask & DB_UNDER) == DB_ICE)) return TRUE;
  66.     return FALSE;
  67. }
  68.  
  69. #endif /* OVL0 */
  70.  
  71. #ifdef OVL1
  72.  
  73. /* 
  74.  * We want to know whether a wall (or a door) is the portcullis (passageway)
  75.  * of an eventual drawbridge.
  76.  *
  77.  * Return value:  the direction of the drawbridge.
  78.  */
  79.  
  80. int
  81. is_drawbridge_wall(x,y)
  82. int x,y;
  83. {
  84.     struct rm *lev;
  85.  
  86.     lev = &levl[x][y];
  87.     if (lev->typ != DOOR && lev->typ != DBWALL)
  88.         return (-1);
  89.  
  90.     if (IS_DRAWBRIDGE(levl[x+1][y].typ) &&
  91.         (levl[x+1][y].drawbridgemask & DB_DIR) == DB_WEST)
  92.         return (DB_WEST);
  93.     if (IS_DRAWBRIDGE(levl[x-1][y].typ) && 
  94.         (levl[x-1][y].drawbridgemask & DB_DIR) == DB_EAST)
  95.         return (DB_EAST);
  96.     if (IS_DRAWBRIDGE(levl[x][y-1].typ) && 
  97.         (levl[x][y-1].drawbridgemask & DB_DIR) == DB_SOUTH)
  98.         return (DB_SOUTH);
  99.     if (IS_DRAWBRIDGE(levl[x][y+1].typ) && 
  100.         (levl[x][y+1].drawbridgemask & DB_DIR) == DB_NORTH)
  101.         return (DB_NORTH);
  102.  
  103.     return (-1);
  104. }
  105.  
  106. /*
  107.  * Use is_db_wall where you want to verify that a
  108.  * drawbridge "wall" is UP in the location x, y
  109.  * (instead of UP or DOWN, as with is_drawbridge_wall). 
  110.  */ 
  111. boolean
  112. is_db_wall(x,y)
  113. int x,y;
  114. {
  115.     return( levl[x][y].typ == DBWALL );
  116. }
  117.  
  118.  
  119. /*
  120.  * Return true with x,y pointing to the drawbridge if x,y initially indicate
  121.  * a drawbridge or drawbridge wall.
  122.  */
  123. boolean
  124. find_drawbridge(x,y)
  125. int *x,*y;
  126. {
  127.     int dir;
  128.  
  129.     if (IS_DRAWBRIDGE(levl[*x][*y].typ))
  130.         return TRUE;
  131.     dir = is_drawbridge_wall(*x,*y);
  132.     if (dir >= 0) {
  133.         switch(dir) {
  134.             case DB_NORTH: (*y)++; break;
  135.             case DB_SOUTH: (*y)--; break;
  136.             case DB_EAST:  (*x)--; break;
  137.             case DB_WEST:  (*x)++; break;
  138.         }
  139.         return TRUE;
  140.     }
  141.     return FALSE;
  142. }
  143.  
  144. #endif /* OVL1 */
  145. #ifdef OVLB
  146.  
  147. /* 
  148.  * Find the drawbridge wall associated with a drawbridge.
  149.  */
  150. static void
  151. get_wall_for_db(x,y)
  152. int *x,*y;
  153. {
  154.     switch (levl[*x][*y].drawbridgemask & DB_DIR) {
  155.         case DB_NORTH: (*y)--; break;
  156.         case DB_SOUTH: (*y)++; break;
  157.         case DB_EAST:  (*x)++; break;
  158.         case DB_WEST:  (*x)--; break;
  159.     }
  160. }
  161.  
  162. /*
  163.  * Creation of a drawbridge at pos x,y.
  164.  *     dir is the direction.
  165.  *     flag must be put to TRUE if we want the drawbridge to be opened.
  166.  */
  167.  
  168. boolean
  169. create_drawbridge(x,y,dir,flag)
  170. int x,y,dir;
  171. boolean flag;
  172. {
  173.     int x2,y2;
  174.     boolean horiz;
  175.     boolean lava = levl[x][y].typ == LAVAPOOL; /* assume initialized map */
  176.  
  177.     x2 = x; y2 = y;
  178.     switch(dir) {
  179.         case DB_NORTH:
  180.             horiz = TRUE;
  181.             y2--;
  182.             break;
  183.         case DB_SOUTH:
  184.             horiz = TRUE;
  185.             y2++;
  186.             break;
  187.         case DB_EAST:
  188.             horiz = FALSE;
  189.             x2++;
  190.             break;
  191.         default:
  192.             impossible("bad direction in create_drawbridge");
  193.             /* fall through */
  194.         case DB_WEST:
  195.             horiz = FALSE;
  196.             x2--;
  197.             break;
  198.     }
  199.     if (!IS_WALL(levl[x2][y2].typ))
  200.         return(FALSE);
  201.     if (flag) {             /* We want the bridge open */
  202.         levl[x][y].typ = DRAWBRIDGE_DOWN;
  203.         levl[x2][y2].typ = DOOR;
  204.         levl[x2][y2].doormask = D_NODOOR;
  205.     } else {
  206.         levl[x][y].typ = DRAWBRIDGE_UP;
  207.         levl[x2][y2].typ = DBWALL;
  208.         /* Drawbridges are non-diggable. */
  209.         levl[x2][y2].diggable = W_NONDIGGABLE;
  210.     }
  211.     levl[x][y].horizontal = !horiz;
  212.     levl[x2][y2].horizontal = horiz;
  213.     levl[x][y].drawbridgemask = dir;
  214.     if(lava) levl[x][y].drawbridgemask |= DB_LAVA;
  215.     return(TRUE);           
  216. }
  217.  
  218. struct entity {
  219.     struct monst *emon;      /* youmonst for the player */
  220.     struct permonst *edata;   /* must be non-zero for record to be valid */
  221.     int ex, ey;
  222. };
  223.  
  224. #define ENTITIES 2
  225.  
  226. static struct entity NEARDATA occupants[ENTITIES];
  227.  
  228. static
  229. struct entity *
  230. e_at(x, y)
  231. int x, y;
  232. {
  233.     int entitycnt;
  234.     
  235.     for (entitycnt = 0; entitycnt < ENTITIES; entitycnt++)
  236.         if ((occupants[entitycnt].edata) && 
  237.             (occupants[entitycnt].ex == x) &&
  238.             (occupants[entitycnt].ey == y))
  239.             break;
  240. #ifdef D_DEBUG
  241.     pline("entitycnt = %d", entitycnt);
  242.     wait_synch();
  243. #endif
  244.     return((entitycnt == ENTITIES)? 
  245.            (struct entity *)0 : &(occupants[entitycnt]));
  246. }
  247.  
  248. static void
  249. m_to_e(mtmp, x, y, etmp)
  250. struct monst *mtmp;
  251. xchar x, y;
  252. struct entity *etmp;
  253. {
  254.     etmp->emon = mtmp;
  255.     if (mtmp) {
  256.         etmp->ex = x;
  257.         etmp->ey = y;
  258.         if (mtmp->wormno && (x != mtmp->mx || y != mtmp->my))
  259.             etmp->edata = &mons[PM_LONG_WORM_TAIL];
  260.         else
  261.             etmp->edata = mtmp->data;
  262.     } else
  263.         etmp->edata = (struct permonst *)0;
  264. }
  265.  
  266. static void
  267. u_to_e(etmp)
  268. struct entity *etmp;
  269. {
  270.     etmp->emon = &youmonst;
  271.     etmp->ex = u.ux;
  272.     etmp->ey = u.uy;
  273.     etmp->edata = uasmon;
  274. }
  275.  
  276. static void
  277. set_entity(x, y, etmp)
  278. int x, y;
  279. struct entity *etmp;
  280. {
  281.     if ((x == u.ux) && (y == u.uy))
  282.         u_to_e(etmp);
  283.     else
  284.         if (MON_AT(x, y))
  285.             m_to_e(m_at(x, y), x, y, etmp);
  286.         else
  287.             etmp->edata = (struct permonst *)0;
  288. }
  289.  
  290. #define is_u(etmp) (etmp->emon == &youmonst)
  291. #define e_canseemon(etmp) (is_u(etmp) ? (boolean)TRUE : canseemon(etmp->emon)) 
  292.  
  293. /*
  294.  * e_strg is a utility routine which is not actually in use anywhere, since 
  295.  * the specialized routines below suffice for all current purposes. 
  296.  */
  297.  
  298. /* #define e_strg(etmp, func) (is_u(etmp)? (char *)0 : func(etmp->emon)) */
  299.  
  300. static char *
  301. e_nam(etmp)
  302. struct entity *etmp;
  303. {
  304.     return(is_u(etmp)? "you" : mon_nam(etmp->emon));
  305. }
  306.  
  307. #ifdef D_DEBUG
  308. /*
  309.  * Enam is another unused utility routine:  E_phrase is preferable.
  310.  */
  311.  
  312. static char *
  313. Enam(etmp)
  314. struct entity *etmp;
  315. {
  316.     return(is_u(etmp)? "You" : Monnam(etmp->emon));
  317. }
  318. #endif /* D_DEBUG */
  319.  
  320. /*
  321.  * Generates capitalized entity name, makes 2nd -> 3rd person conversion on 
  322.  * verb, where necessary.
  323.  */
  324.  
  325. static char *
  326. E_phrase(etmp, verb)
  327. struct entity *etmp;
  328. const char *verb;
  329. {
  330.     static char wholebuf[80];
  331.     char verbbuf[30];
  332.  
  333.     if (is_u(etmp)) 
  334.         Strcpy(wholebuf, "You");
  335.     else
  336.         Strcpy(wholebuf, Monnam(etmp->emon));
  337.     if (!*verb)
  338.         return(wholebuf);
  339.     Strcat(wholebuf, " ");
  340.     verbbuf[0] = '\0';
  341.     if (is_u(etmp)) 
  342.         Strcpy(verbbuf, verb);
  343.     else {
  344.         if (!strcmp(verb, "are"))
  345.             Strcpy(verbbuf, "is");
  346.         if (!strcmp(verb, "have"))
  347.             Strcpy(verbbuf, "has");
  348.         if (!verbbuf[0]) {
  349.             Strcpy(verbbuf, verb);
  350.             switch (verbbuf[strlen(verbbuf) - 1]) {
  351.                 case 'y':
  352.                     verbbuf[strlen(verbbuf) - 1] = '\0';
  353.                     Strcat(verbbuf, "ies");
  354.                     break;
  355.                 case 'h':
  356.                 case 'o':
  357.                 case 's':
  358.                     Strcat(verbbuf, "es");
  359.                     break;
  360.                 default:
  361.                     Strcat(verbbuf, "s");
  362.                     break;
  363.             }
  364.         }
  365.     }
  366.     Strcat(wholebuf, verbbuf);
  367.     return(wholebuf);
  368. }
  369.  
  370. /*
  371.  * Simple-minded "can it be here?" routine
  372.  */
  373.  
  374. static boolean
  375. e_survives_at(etmp, x, y)
  376. struct entity *etmp;
  377. int x, y;
  378. {
  379.     if (noncorporeal(etmp->edata))
  380.         return(TRUE);
  381.     if (is_pool(x, y))
  382.         return((is_u(etmp) && (Wwalking || Magical_breathing || Levitation)) ||
  383.                is_swimmer(etmp->edata) || is_flyer(etmp->edata) ||
  384.                is_floater(etmp->edata));
  385.     /* must force call to lava_effects in e_died if is_u */
  386.     if (is_lava(x, y))
  387.         return(is_u(etmp) ? !!Levitation : resists_fire(etmp->edata));
  388.     if (is_db_wall(x, y))
  389.         return(passes_walls(etmp->edata));
  390.     return(TRUE);
  391. }
  392.  
  393. static void
  394. e_died(etmp, dest, how)
  395. struct entity *etmp;
  396. int dest, how;
  397. {
  398.     if (is_u(etmp)) {
  399.         if (how == DROWNING)
  400.             (void) drown();
  401.         if (how == BURNING)
  402.             (void) lava_effects();
  403.         else {
  404.             coord xy;
  405.  
  406.             killer_format = KILLED_BY_AN;
  407.             killer = "falling drawbridge";
  408.             done(how);
  409.             /* So, you didn't die */
  410.             if (!e_survives_at(etmp, etmp->ex, etmp->ey)) {
  411.                 if (enexto(&xy, etmp->ex, etmp->ey,
  412.                                 etmp->edata)) {
  413.                 pline("A %s force teleports you away...",
  414.                       Hallucination ? "normal" : "strange");
  415.                 teleds(xy.x, xy.y);
  416.                 }
  417.                 /* otherwise on top of the drawbridge is the
  418.                  * only viable spot in the dungeon, so stay there
  419.                  */
  420.             }
  421.         }
  422.     } else {
  423.         xkilled(etmp->emon, dest);
  424.         etmp->edata = (struct permonst *)0;    
  425.     }
  426. }
  427.  
  428.  
  429. /*
  430.  * These are never directly affected by a bridge or portcullis.
  431.  */
  432.  
  433. static boolean
  434. automiss(etmp)
  435. struct entity *etmp;
  436. {
  437.     return(passes_walls(etmp->edata) || noncorporeal(etmp->edata));
  438. }
  439.  
  440. /*
  441.  * Does falling drawbridge or portcullis miss etmp?
  442.  */
  443.  
  444. static boolean
  445. e_missed(etmp, chunks)
  446. struct entity *etmp;
  447. boolean chunks;
  448. {
  449.     int misses;
  450.  
  451. #ifdef D_DEBUG
  452.     if (chunks)
  453.         pline("Do chunks miss?");
  454. #endif
  455.     if (automiss(etmp))
  456.         return(TRUE);    
  457.  
  458.     if (is_flyer(etmp->edata) && 
  459.         (is_u(etmp)? !Sleeping : 
  460.          (etmp->emon->mcanmove && !etmp->emon->msleep)))
  461.                          /* flying requires mobility */
  462.         misses = 5;    /* out of 8 */    
  463.     else
  464.         if (is_floater(etmp->edata) ||
  465.             (is_u(etmp) && Levitation))     /* doesn't require mobility */
  466.             misses = 3;
  467.         else
  468.             if (chunks && is_pool(etmp->ex, etmp->ey))
  469.                 misses = 2;             /* sitting ducks */
  470.             else
  471.                 misses = 0;      
  472.  
  473.     if (is_db_wall(etmp->ex, etmp->ey))
  474.         misses -= 3;                    /* less airspace */
  475.  
  476. #ifdef D_DEBUG
  477.     pline("Miss chance = %d (out of 8)", misses);
  478. #endif
  479.  
  480.     return((misses >= rnd(8))? TRUE : FALSE);
  481. }
  482.  
  483. /*
  484.  * Can etmp jump from death?
  485.  */ 
  486.  
  487. static boolean
  488. e_jumps(etmp)
  489. struct entity *etmp;
  490. {
  491.     int tmp = 4;         /* out of 10 */
  492.  
  493.     if (is_u(etmp)? (Sleeping || Fumbling) : 
  494.                 (!etmp->emon->mcanmove || etmp->emon->msleep || 
  495.              !etmp->edata->mmove   || etmp->emon->wormno))
  496.         return(FALSE);
  497.  
  498.     if (is_u(etmp)? Confusion : etmp->emon->mconf)
  499.         tmp -= 2;
  500.  
  501.     if (is_u(etmp)? Stunned : etmp->emon->mstun)
  502.         tmp -= 3;
  503.  
  504.     if (is_db_wall(etmp->ex, etmp->ey))
  505.         tmp -= 2;                /* less room to maneuver */
  506.     
  507. #ifdef D_DEBUG
  508.     pline("%s to jump (%d chances in 10)", E_phrase(etmp, "try"), tmp);
  509. #endif
  510.     return((tmp >= rnd(10))? TRUE : FALSE);
  511. }
  512.  
  513. static void
  514. do_entity(etmp)
  515. struct entity *etmp;
  516. {
  517.     int newx, newy, at_portcullis, oldx, oldy;
  518.     boolean must_jump = FALSE, relocates = FALSE, e_inview;
  519.     struct rm *crm;
  520.  
  521.     if (!etmp->edata)
  522.         return;
  523.  
  524.     e_inview = e_canseemon(etmp);
  525.  
  526.     oldx = etmp->ex;
  527.     oldy = etmp->ey;
  528.  
  529.     at_portcullis = is_db_wall(oldx, oldy);
  530.  
  531.     crm = &levl[oldx][oldy];
  532.  
  533.     if (automiss(etmp) && e_survives_at(etmp, oldx, oldy)) {
  534.         char edifice[20];
  535.  
  536.         if (e_inview) {
  537.             *edifice = '\0';
  538.             if ((crm->typ == DRAWBRIDGE_DOWN) ||
  539.                     (crm->typ == DRAWBRIDGE_UP))
  540.                 Strcpy(edifice, "drawbridge");
  541.             else
  542.                      if (at_portcullis) 
  543.                     Strcpy(edifice, "portcullis");
  544.             if (*edifice)
  545.                 pline("The %s passes through %s!", edifice, 
  546.                             e_nam(etmp));            
  547.         }
  548.         return;
  549.     }
  550.     if (e_missed(etmp, FALSE)) { 
  551.         if (at_portcullis)
  552.             pline("The portcullis misses %s!",
  553.                   e_nam(etmp));
  554. #ifdef D_DEBUG
  555.         else
  556.             pline("The drawbridge misses %s!", 
  557.                   e_nam(etmp));
  558. #endif
  559.         if (e_survives_at(etmp, oldx, oldy)) 
  560.             return;
  561.         else {
  562. #ifdef D_DEBUG
  563.             pline("Mon can't survive here");
  564. #endif
  565.             if (at_portcullis)
  566.                 must_jump = TRUE;
  567.             else
  568.                 relocates = TRUE; /* just ride drawbridge in */
  569.         }
  570.     } else {
  571.         if (crm->typ == DRAWBRIDGE_DOWN) {
  572.             pline("%s crushed underneath the drawbridge.",
  573.                         E_phrase(etmp, "are"));             /* no jump */
  574.             e_died(etmp, e_inview? 3 : 2, CRUSHING);/* no corpse */
  575.             return;   /* Note: Beyond this point, we know we're  */
  576.         }                 /* not at an opened drawbridge, since all  */
  577.         must_jump = TRUE; /* *missable* creatures survive on the     */
  578.     }              /* square, and all the unmissed ones die.  */
  579.     if (must_jump) {
  580.         if (at_portcullis) {
  581.         if (e_jumps(etmp)) {
  582.             relocates = TRUE;
  583. #ifdef D_DEBUG
  584.             pline("Jump succeeds!");
  585. #endif
  586.         } else {
  587.             if (e_inview)
  588.             pline("%s crushed by the falling portcullis!",
  589.                   E_phrase(etmp, "are"));
  590.             else if (flags.soundok)
  591.             You("hear a crushing sound.");
  592.             e_died(etmp, e_inview? 3 : 2, CRUSHING);
  593.             /* no corpse */
  594.             return;
  595.         }
  596.         } else { /* tries to jump off bridge to original square */
  597.         relocates = !e_jumps(etmp); 
  598. #ifdef D_DEBUG
  599.         pline("Jump %s!", (relocates)? "fails" : "succeeds");
  600. #endif
  601.         }
  602.     }
  603.  
  604. /*
  605.  * Here's where we try to do relocation.  Assumes that etmp is not arriving
  606.  * at the portcullis square while the drawbridge is falling, since this square
  607.  * would be inaccessible (i.e. etmp started on drawbridge square) or 
  608.  * unnecessary (i.e. etmp started here) in such a situation.
  609.  */
  610. #ifdef D_DEBUG
  611.     pline("Doing relocation.");
  612. #endif
  613.     newx = oldx;
  614.     newy = oldy;
  615.     (void)find_drawbridge(&newx, &newy);
  616.     if ((newx == oldx) && (newy == oldy))
  617.         get_wall_for_db(&newx, &newy);
  618. #ifdef D_DEBUG
  619.     pline("Checking new square for occupancy.");
  620. #endif
  621.     if (relocates && (e_at(newx, newy))) { 
  622.  
  623. /* 
  624.  * Standoff problem:  one or both entities must die, and/or both switch 
  625.  * places.  Avoid infinite recursion by checking first whether the other 
  626.  * entity is staying put.  Clean up if we happen to move/die in recursion.
  627.  */
  628.         struct entity *other;
  629.  
  630.         other = e_at(newx, newy);
  631. #ifdef D_DEBUG
  632.         pline("New square is occupied by %s", e_nam(other));
  633. #endif
  634.         if (e_survives_at(other, newx, newy) && automiss(other)) {
  635.             relocates = FALSE;               /* "other" won't budge */
  636. #ifdef D_DEBUG
  637.             pline("%s suicide.", E_phrase(etmp, "commit"));
  638. #endif
  639.         } else {
  640.  
  641. #ifdef D_DEBUG
  642.             pline("Handling %s", e_nam(other));
  643. #endif
  644.             while ((e_at(newx, newy)) && 
  645.                    (e_at(newx, newy) != etmp))
  646.                        do_entity(other);
  647. #ifdef D_DEBUG
  648.             pline("Checking existence of %s", e_nam(etmp));
  649.             wait_synch();
  650. #endif
  651.             if (e_at(oldx, oldy) != etmp) {
  652. #ifdef D_DEBUG
  653.                 pline("%s moved or died in recursion somewhere",
  654.                   E_phrase(etmp, "have"));
  655.                 wait_synch();
  656. #endif
  657.                 return;
  658.             }
  659.         }
  660.     }
  661.     if (relocates && !e_at(newx, newy)) {/* if e_at() entity = worm tail */
  662. #ifdef D_DEBUG
  663.         pline("Moving %s", e_nam(etmp));
  664. #endif
  665.         if (!is_u(etmp)) {
  666.             remove_monster(etmp->ex, etmp->ey);
  667.             place_monster(etmp->emon, newx, newy);
  668.         } else {
  669.             u.ux = newx;
  670.             u.uy = newy;
  671.         }
  672.         etmp->ex = newx;
  673.         etmp->ey = newy;
  674.         e_inview = e_canseemon(etmp);
  675.     }
  676. #ifdef D_DEBUG
  677.     pline("Final disposition of %s", e_nam(etmp));
  678.     wait_synch();
  679. #endif
  680.     if (is_db_wall(etmp->ex, etmp->ey)) {
  681. #ifdef D_DEBUG
  682.         pline("%s in portcullis chamber", E_phrase(etmp, "are"));
  683.         wait_synch();
  684. #endif
  685.         if (e_inview) {
  686.             if (is_u(etmp)) {
  687.                 You("tumble towards the closed portcullis!"); 
  688.                 if (automiss(etmp))
  689.                     You("pass through it!");
  690.                 else
  691.                     pline("The drawbridge closes in...");
  692.             } else
  693.                 pline("%s behind the drawbridge.",
  694.                                   E_phrase(etmp, "disappear"));
  695.         }
  696.         if (!e_survives_at(etmp, etmp->ex, etmp->ey)) {
  697.             killer_format = KILLED_BY_AN;
  698.             killer = "closing drawbridge";
  699.             e_died(etmp, 0, CRUSHING);            /* no message */
  700.             return;
  701.         }
  702. #ifdef D_DEBUG
  703.         pline("%s in here", E_phrase(etmp, "survive"));
  704. #endif
  705.     } else {
  706. #ifdef D_DEBUG
  707.         pline("%s on drawbridge square", E_phrase(etmp, "are"));
  708. #endif
  709.         if (is_pool(etmp->ex, etmp->ey) && !e_inview)
  710.             if (flags.soundok)
  711.                 You("hear a splash.");
  712.         if (e_survives_at(etmp, etmp->ex, etmp->ey)) {
  713.             if (e_inview && !is_flyer(etmp->edata) &&
  714.                 !is_floater(etmp->edata))
  715.                 pline("%s from the bridge.",
  716.                                   E_phrase(etmp, "fall"));    
  717.             return;    
  718.         }
  719. #ifdef D_DEBUG
  720.         pline("%s cannot survive on the drawbridge square",Enam(etmp));
  721. #endif
  722.         if (is_pool(etmp->ex, etmp->ey) || is_lava(etmp->ex, etmp->ey))
  723.             if (e_inview && !is_u(etmp)) {
  724.             /* drown() will supply msgs if nec. */
  725.             boolean lava = is_lava(etmp->ex, etmp->ey);
  726.  
  727.             if (Hallucination)
  728.                 pline("%s the %s and disappears.",
  729.                   E_phrase(etmp, "drink"),
  730.                   lava ? "lava" : "moat");
  731.             else
  732.                 pline("%s into the %s.",
  733.                   E_phrase(etmp, "fall"),
  734.                   lava ? "lava" : "moat");
  735.             }
  736.         killer_format = NO_KILLER_PREFIX;
  737.         killer = "fell from a drawbridge";
  738.         e_died(etmp, e_inview ? 3 : 2,      /* CRUSHING is arbitrary */
  739.                (is_pool(etmp->ex, etmp->ey)) ? DROWNING :
  740.                (is_lava(etmp->ex, etmp->ey)) ? BURNING :
  741.                                CRUSHING); /*no corpse*/
  742.         return;
  743.     }
  744. }
  745.  
  746. /*
  747.  * Close the drawbridge located at x,y
  748.  */
  749.  
  750. void
  751. close_drawbridge(x,y)
  752. int x,y;
  753. {
  754.     register struct rm *lev1, *lev2;
  755.     int x2, y2;
  756.  
  757.     lev1 = &levl[x][y];
  758.     if (lev1->typ != DRAWBRIDGE_DOWN) return;
  759.     x2 = x; y2 = y;
  760.     get_wall_for_db(&x2,&y2);
  761.     if (cansee(x,y))  /* change msgs if you are a w-walker at portcullis */
  762.         You("see a drawbridge %s up!", 
  763.             ((u.ux == x2) && (u.uy == y2))? "coming" : "going");
  764.     lev1->typ = DRAWBRIDGE_UP;
  765.     lev2 = &levl[x2][y2];
  766.     lev2->typ = DBWALL;
  767.     switch (lev1->drawbridgemask & DB_DIR) {
  768.         case DB_NORTH:
  769.         case DB_SOUTH:
  770.             lev2->horizontal = TRUE;
  771.             break;
  772.         case DB_WEST:
  773.         case DB_EAST:
  774.             lev2->horizontal = FALSE;
  775.             break;
  776.     }
  777.     lev2->diggable = W_NONDIGGABLE;
  778.     set_entity(x, y, &(occupants[0]));
  779.     set_entity(x2, y2, &(occupants[1]));
  780.     do_entity(&(occupants[0]));        /* Do set_entity after first */
  781.     set_entity(x2, y2, &(occupants[1]));    /* do_entity for worm tail */
  782.     do_entity(&(occupants[1]));
  783.     if(OBJ_AT(x,y) && flags.soundok)
  784.         You("hear smashing and crushing.");
  785.     (void) revive_nasty(x,y,NULL);
  786.     (void) revive_nasty(x2,y2,NULL);
  787.     delallobj(x, y);
  788.     newsym(x, y);
  789.     delallobj(x2, y2);
  790.     newsym(x2, y2);
  791.     block_point(x2,y2);    /* vision */
  792. }
  793.  
  794. /* 
  795.  * Open the drawbridge located at x,y
  796.  */
  797.  
  798. void
  799. open_drawbridge(x,y)
  800. int x,y;
  801. {
  802.     register struct rm *lev1, *lev2;
  803.     int x2, y2;
  804.  
  805.     lev1 = &levl[x][y];
  806.     if (lev1->typ != DRAWBRIDGE_UP) return;
  807.     x2 = x; y2 = y;
  808.     get_wall_for_db(&x2,&y2);
  809.     if (cansee(x,y))  /* change msgs if you are a w-walker at portcullis */
  810.         You("see a drawbridge %s down!",
  811.             ((x2 == u.ux) && (y2 == u.uy))? "going" : "coming");
  812.     lev1->typ = DRAWBRIDGE_DOWN;
  813.     lev2 = &levl[x2][y2];
  814.     lev2->typ = DOOR;
  815.     lev2->doormask = D_NODOOR;
  816.     set_entity(x, y, &(occupants[0]));
  817.     set_entity(x2, y2, &(occupants[1]));
  818.     do_entity(&(occupants[0]));        /* do set_entity after first */
  819.     set_entity(x2, y2, &(occupants[1]));    /* do_entity for worm tails */
  820.     do_entity(&(occupants[1]));
  821.     spoteffects();  /* if underwater, hero is now on solid ground */
  822.     (void) revive_nasty(x,y,NULL);
  823.     delallobj(x, y);
  824.     newsym(x, y);
  825.     newsym(x2, y2);
  826.     unblock_point(x2,y2);    /* vision */
  827.     if (Is_stronghold(&u.uz)) u.uevent.uopened_dbridge = TRUE;
  828. }
  829.  
  830. /*
  831.  * Let's destroy the drawbridge located at x,y
  832.  */
  833.  
  834. void
  835. destroy_drawbridge(x,y)
  836. int x,y;
  837. {
  838.     register struct rm *lev1, *lev2;
  839.     int x2, y2;
  840.     boolean e_inview;
  841.     struct entity *etmp1 = &(occupants[0]), *etmp2 = &(occupants[1]);
  842.  
  843.     lev1 = &levl[x][y];
  844.     if (!IS_DRAWBRIDGE(lev1->typ))
  845.         return;
  846.     x2 = x; y2 = y;
  847.     get_wall_for_db(&x2,&y2);
  848.     lev2 = &levl[x2][y2];
  849.     if ((lev1->drawbridgemask & DB_UNDER) == DB_MOAT ||
  850.         (lev1->drawbridgemask & DB_UNDER) == DB_LAVA) {
  851.         struct obj *otmp;
  852.         boolean lava = (lev1->drawbridgemask & DB_UNDER) == DB_LAVA;
  853.         if (lev1->typ == DRAWBRIDGE_UP) {
  854.             if (cansee(x2,y2))
  855.                 pline("The portcullis of the drawbridge falls into the %s!",
  856.                   lava ? "lava" : "moat");
  857.             else if (flags.soundok)
  858.                 You("hear a loud *SPLASH*!");
  859.         } else {
  860.             if (cansee(x,y))
  861.                 pline("The drawbridge collapses into the %s!",
  862.                   lava ? "lava" : "moat");
  863.             else if (flags.soundok)
  864.                 You("hear a loud *SPLASH*!");
  865.         }
  866.         lev1->typ = lava ? LAVAPOOL : MOAT;
  867.         lev1->drawbridgemask = 0;
  868.         if(otmp = sobj_at(BOULDER,x,y)) {
  869.             freeobj(otmp);
  870.             (void) flooreffects(otmp,x,y,"fall");
  871.         }
  872.     } else {
  873.         if (cansee(x,y))
  874.             pline("The drawbridge disintegrates!");
  875.         else
  876.             You("hear a loud *CRASH*!");
  877.         lev1->typ =
  878.             ((lev1->drawbridgemask & DB_ICE) ? ICE : ROOM);
  879.         lev1->icedpool =
  880.             ((lev1->drawbridgemask & DB_ICE) ? ICED_MOAT : 0);
  881.     }
  882.     wake_nearby();
  883.     lev2->typ = DOOR;
  884.     lev2->doormask = D_NODOOR;
  885.     newsym(x,y);
  886.     newsym(x2,y2);
  887.     if (!does_block(x2,y2,lev2)) unblock_point(x2,y2);    /* vision */
  888.     if (Is_stronghold(&u.uz)) u.uevent.uopened_dbridge = TRUE;
  889.  
  890.     set_entity(x2, y2, etmp2); /* currently only automissers can be here */
  891.     if (etmp2->edata) {
  892.         e_inview = e_canseemon(etmp2);
  893.         if (!automiss(etmp2)) {
  894.             if (e_inview)
  895.                 pline("%s blown apart by flying debris.",
  896.                             E_phrase(etmp2, "are"));
  897.             killer_format = KILLED_BY_AN;
  898.             killer = "exploding drawbridge";
  899.             e_died(etmp2, e_inview? 3 : 2, CRUSHING); /*no corpse*/
  900.         }         /* nothing which is vulnerable can survive this */
  901.     }
  902.     set_entity(x, y, etmp1);
  903.     if (etmp1->edata) {
  904.         e_inview = e_canseemon(etmp1);
  905.         if (e_missed(etmp1, TRUE)) {
  906. #ifdef D_DEBUG
  907.             pline("%s spared!", E_phrase(etmp1, "are"));
  908. #endif
  909.         } else {
  910.             if (e_inview) {
  911.                 if (!is_u(etmp1) && Hallucination)
  912.                 pline("%s into some heavy metal",
  913.                       E_phrase(etmp1, "get"));
  914.                 else
  915.                 pline("%s hit by a huge chunk of metal!",
  916.                       E_phrase(etmp1, "are"));
  917.             } else {
  918.                 if (flags.soundok && !is_u(etmp1) && !is_pool(x,y))
  919.                 You("hear a crushing sound");
  920. #ifdef D_DEBUG
  921.                 else
  922.                 pline("%s from shrapnel", 
  923.                       E_phrase(etmp1, "die"));
  924. #endif
  925.             }
  926.             killer_format = KILLED_BY_AN;
  927.             killer = "collapsing drawbridge";
  928.             e_died(etmp1, e_inview? 3 : 2, CRUSHING); /*no corpse*/
  929.             if(lev1->typ == MOAT) do_entity(etmp1);
  930.         }
  931.     }
  932. }
  933.  
  934.  
  935. #endif /* OVLB */
  936.  
  937. /*dbridge.c*/
  938.